package com.object.bases;

/*
##Override
    Override和Overload不同的是，如果方法签名如果不同，就是Overload，Overload方法是一个新方法；如果方法签名相同，并且返回值也相同，就是Override。
     注意：方法名相同，方法参数相同，但方法返回值不同，也是不同的方法。在Java程序中，出现这种情况，编译器会报错。
     加上@Override可以让编译器帮助检查是否进行了正确的覆写。希望进行覆写，但是不小心写错了方法签名，编译器会报错。
     但是@Override不是必需的。
     在上一节中，我们已经知道，引用变量的声明类型可能与其实际类型不符，
##多态
    多态是指，针对某个类型的方法调用，其真正执行的方法取决于运行时期实际类型的方法。
    一个实际类型为Student，引用类型为Person的变量，调用其run()方法，调用的是Person还是Student的run()方法？
    运行一下上面的代码就可以知道，实际上调用的方法是Student的run()方法。因此可得出结论：
    Java的实例方法调用是基于运行时的实际类型的动态调用，而非变量的声明类型。
    这个非常重要的特性在面向对象编程中称之为多态。它的英文拼写非常复杂：Polymorphic。

##覆写Object方法
    因为所有的class最终都继承自Object，而Object定义了几个重要的方法：
    toString()：把instance输出为String；
    equals()：判断两个instance是否逻辑相等；
    hashCode()：计算一个instance的哈希值。
## 调用super
    在子类的覆写方法中，如果要调用父类的被覆写的方法，可以通过super来调用。
##final
    继承可以允许子类覆写父类的方法。如果一个父类不允许子类对它的某个方法进行覆写，可以把该方法标记为final。用final修饰的方法不能被Override
    如果一个类不希望任何其他类继承自它，那么可以把这个类本身标记为final。用final修饰的类不能被继承：
    对于一个类的实例字段，同样可以用final修饰。用final修饰的字段在初始化后不能被修改。
    对final字段重新赋值会报错
    可以在构造方法中初始化final字段：
##小结
    子类可以覆写父类的方法（Override），覆写在子类中改变了父类方法的行为；
    Java的方法调用总是作用于运行期对象的实际类型，这种行为称为多态；
    final修饰符有多种作用：
    final修饰的方法可以阻止被覆写；
    final修饰的class可以阻止被继承；
    final修饰的field必须在创建对象时初始化，随后不可修改。
 */


public class Polymorphism {

    //多态的案例
    public static void main(String[] args) {
        // 给一个有普通收入、工资收入和享受国务院特殊津贴的小伙伴算税:
        Income[] incomes = new Income[] {
                new Income(3000),
                new Salary(7500),
                new StateCouncilSpecialAllowance(15000)
        };
        System.out.println(totalTax(incomes));
    }

    public static double totalTax(Income... incomes) {
        double total = 0;
        for (Income income: incomes) {
            total = total + income.getTax();
        }
        return total;

    }
}
class Income {
    protected double income;

    public Income(double income) {
        this.income = income;
    }

    public double getTax() {
        return income * 0.1; // 税率10%
    }
}

class Salary extends Income {
    public Salary(double income) {
        super(income);
    }

    @Override
    public double getTax() {
        if (income <= 5000) {
            return 0;
        }
        return (income - 5000) * 0.2;
    }
}

class StateCouncilSpecialAllowance extends Income {
    public StateCouncilSpecialAllowance(double income) {
        super(income);
    }

    @Override
    public double getTax() {
        return 0;
    }
}